package com.immediatus.graphics.texture.region;

import com.immediatus.graphics.buffer.TextureRegionBuffer;
import com.immediatus.graphics.contracts.ITexture;
import com.immediatus.graphics.util.OpenGLWrapper;

import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;


public abstract class BaseTextureRegion{

    public abstract float getTextureCoordinateX1();

    public abstract float getTextureCoordinateY1();

    public abstract float getTextureCoordinateX2();

    public abstract float getTextureCoordinateY2();

    private final ITexture _texture;
    private final TextureRegionBuffer _textureRegionBuffer;

    private int _width;
    private int _height;

    private int _x;
    private int _y;

    public BaseTextureRegion(final ITexture texture_, final int x_, final int y_, final int w_, final int h_){
        this._texture = texture_;
        this._x = x_;
        this._y = y_;
        this._width = w_;
        this._height = h_;

        this._textureRegionBuffer = new TextureRegionBuffer(this, GL11.GL_STATIC_DRAW, true);

        this.initTextureBuffer();
    }

    protected void initTextureBuffer(){
        this.updateTextureRegionBuffer();
    }

    protected abstract BaseTextureRegion deepCopy();

    public int getWidth(){
        return this._width;
    }

    public int getHeight(){
        return this._height;
    }

    public void setWidth(final int width_){
        this._width = width_;
        this.updateTextureRegionBuffer();
    }

    public void setHeight(final int height_){
        this._height = height_;
        this.updateTextureRegionBuffer();
    }

    public void setTexturePosition(final int x_, final int y_){
        this._x = x_;
        this._y = y_;
        this.updateTextureRegionBuffer();
    }

    public int getX(){
        return this._x;
    }

    public int getY(){
        return this._y;
    }

    public ITexture getTexture(){
        return this._texture;
    }

    public TextureRegionBuffer getTextureBuffer(){
        return this._textureRegionBuffer;
    }

    public boolean isFlippedHorizontal(){
        return this._textureRegionBuffer.isFlippedHorizontal();
    }

    public void setFlippedHorizontal(final boolean flippedHorizontal_){
        this._textureRegionBuffer.setFlippedHorizontal(flippedHorizontal_);
    }

    public boolean isFlippedVertical(){
        return this._textureRegionBuffer.isFlippedVertical();
    }

    public void setFlippedVertical(final boolean flippedVertical_){
        this._textureRegionBuffer.setFlippedVertical(flippedVertical_);
    }

    public boolean isTextureRegionBufferManaged(){
        return this._textureRegionBuffer.isManaged();
    }

    public void setTextureRegionBufferManaged(final boolean textureRegionBufferManaged_){
        this._textureRegionBuffer.setManaged(textureRegionBufferManaged_);
    }

    protected void updateTextureRegionBuffer(){
        this._textureRegionBuffer.update();
    }

    public void onApply(final GL10 gl_){
        this._texture.bind(gl_);

        if (OpenGLWrapper.EXTENSIONS_VERTEXBUFFEROBJECTS){
            final GL11 gl11 = (GL11) gl_;

            this._textureRegionBuffer.selectOnHardware(gl11);
            OpenGLWrapper.texCoordZeroPointer(gl11);
        } else{
            OpenGLWrapper.texCoordPointer(gl_, this._textureRegionBuffer.getFloatBuffer());
        }
    }
}
